package leaf.science.ui.rightmenu
{
	import caurina.transitions.Tweener;
	
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.KeyboardEvent;
	import flash.events.MouseEvent;
	import flash.filters.BlurFilter;
	import flash.ui.Keyboard;

	public class RightMenu extends Sprite
	{
		
		private var _data:Array;
		private var _items:Array;
		private var _itemsContainer:Sprite;
		private var _selectedItem:RightMenuItem;
		
		private var _radius:Number;
		private var _spread:Number;
		
		private var _isOpen:Boolean;
		
		private var _mask:Sprite;
		
		private var _bar:RightMenuBar;
		public var defaultText:String;
		
		public function RightMenu(defaultText:String)
		{
			this.defaultText = defaultText;
			visible = false;
			setup();
		}
		
		public function set data (data:Array):void
		{
			_data = data;
			buildFromData();
		}
		
		public function get data ():Array
		{
			return _data;
		}
		
		private function setup ():void
		{
			_items = new Array();
			_itemsContainer = new Sprite();
			_itemsContainer.cacheAsBitmap = true;
			addChild(_itemsContainer);
			
			_radius = 290;
			_spread = 10;
			
			_mask = new RightMenuMask();
			_mask.cacheAsBitmap = true;
			_itemsContainer.mask = _mask;
			addChild(_mask);
			
			
			_bar = new RightMenuBar();
			_bar.addEventListener('up', onBarClick);
			_bar.addEventListener('down', onBarClick);
			_bar.text = defaultText;
			addChild(_bar);
			
			
			addEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
			addEventListener(MouseEvent.MOUSE_WHEEL, onMouseWheel);
		}
		
		private function onAddedToStage (evt:Event):void
		{
			// the main app should pass the events:
//			stage.addEventListener(KeyboardEvent.KEY_UP, onKeyUp);
//			stage.addEventListener(MouseEvent.MOUSE_WHEEL, onMouseWheel);
		}
		
		private function onBarClick (evt:Event):void
		{
			switch (evt.type){
				case 'down' :
				selectedIndex ++;
				break;
				
				case 'up' :
				selectedIndex --;
				break;
			}
		}
		
		public function onKeyUp (evt:KeyboardEvent):void
		{
			switch (evt.keyCode){
				case Keyboard.DOWN :
				case Keyboard.RIGHT :
				selectedIndex ++;
				break;
				
				case Keyboard.UP :
				case Keyboard.LEFT :
				selectedIndex --;
				break;
				
				case Keyboard.SPACE :
				if (_isOpen) close();
				else open();
				break;
			}
		}
		
		public function onMouseWheel (evt:MouseEvent):void
		{
			var delta:int = evt.delta > 0 ? 1 : -1;
			selectedIndex -= delta; 
		}
		
		public function close ():void
		{
			
			for each (var item:RightMenuItem in _items){
				Tweener.removeTweens(item);
				Tweener.removeTweens(_itemsContainer);
				item.filters = [new BlurFilter(0,0,2)];
				var angle:Number = - _itemsContainer.rotation;
				Tweener.addTween(item, {rotation:angle, _blur_blurY:20, time:0.3, transition:'easeInQuart', onComplete:onCloseComplete, onCompleteParams:[item]});
			}
			Tweener.addTween(_bar, {x:_radius - 44 - _bar.width, time:0.3, delay:0.3, onComplete:function():void{center(); visible = false}});
			
			_isOpen = false;
			_bar.text = '';
		}
		
		
		public function open ():void
		{
			visible = true;
			Tweener.addTween(_bar, {x:_radius - 44, time:0.3, onComplete:openItems});
			_isOpen = true;
		}
		
		private function openItems ():void
		{
			var angle:Number = _items.length/-2 * _spread;
			for each (var item:RightMenuItem in _items){
				Tweener.removeTweens(item);
				item.visible = true;
				item.filters = [new BlurFilter(0,20,2)];
				Tweener.addTween(item, {rotation:angle, _blur_blurY:0, time:0.3});
				angle += _spread;
			}
			_bar.text = defaultText;
		}
		
		public function get isOpen ():Boolean
		{
			return _isOpen;
		}
		
		public function set selectedItem (item:RightMenuItem):void
		{
			if (_selectedItem == item || !_isOpen) return;
			
			var dest:Number = -item.rotation;
			var time:Number = 1 - 8 / Math.abs(dest - _itemsContainer.rotation);
			_itemsContainer.filters = [new BlurFilter(0,20,2)];
			Tweener.addTween(_itemsContainer, {rotation:dest, _blur_blurY:0, time:time}); 
			_selectedItem = item;
			_bar.text = _selectedItem.text;
			dispatchEvent(new Event(Event.CHANGE));
		}
		
		public function get selectedItem ():RightMenuItem
		{
			return _selectedItem;
		}
		
		public function set selectedIndex (value:int):void
		{
			value = Math.min(Math.max(value, 0), _items.length-1);
			selectedItem = _items[value];
		}
		
		public function get selectedIndex ():int
		{
			if (_selectedItem) return _selectedItem.index
			else return -1;
		}
		
		public function get selectedID ():int
		{
			if (_selectedItem) return _selectedItem.id
			else return -1;
		}
		
		public function set selectedID (value:int):void
		{
			for each (var item:RightMenuItem in _items){
				if (item.id == value){
					selectedItem = item;
					return;
				}
			}
		}
		
		
		private function clear ():void
		{
			_items = new Array();
			if (_itemsContainer && contains(_itemsContainer)){
				removeChild(_itemsContainer);
			}
			_itemsContainer = new Sprite();
			_itemsContainer.cacheAsBitmap = true;
			_itemsContainer.mask = _mask;
			addChildAt(_itemsContainer,0);
		}
		
		private function buildFromData():void
		{
			clear();
			var count:uint;
			var item:RightMenuItem;
			for each (var dataItem:Object in _data){
				item = new RightMenuItem(dataItem.id, dataItem.title);
				item.radius(_radius);
				item.index = count;
				item.addEventListener(MouseEvent.CLICK, onItemClick);
				_itemsContainer.addChild(item);
				_items.push(item);
				
				count ++;
			}
			redraw();
			center();
		}
		
		private function onItemClick (evt:MouseEvent):void
		{
			var item:RightMenuItem = evt.target as RightMenuItem;
			selectedItem = item;
		}
		
		private function redraw ():void
		{
			var angle:Number = _items.length/-2 * _spread;
			for each (var item:RightMenuItem in _items){
				if (_isOpen){
					item.rotation = angle;
					angle += _spread;
				} else {
					item.rotation = 0;
					item.visible = false;
				}
			}
			
			_mask.width = _radius+200;
			_mask.height = (_radius+200)*2;
			
			_bar.x = _radius - 44 - (_isOpen ? 0 : _bar.width);
		}
		
		private function onCloseComplete(item:RightMenuItem):void
		{
			item.rotation = 0;
			item.visible = false;
//			center()	
		}
		
		private function center ():void
		{
			_selectedItem = _items[int(_items.length/2)];
			_itemsContainer.rotation = 0;
			
		}
		
	}
}